package org.gdstash.ui;

import org.gdstash.ui.select.ItemSetSelectionPane;
import org.gdstash.ui.table.GDItemSetCollectionSorter;
import org.gdstash.ui.table.GDItemSetCollectionTableModel;
import org.gdstash.ui.table.GDItemSetInfo;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.util.GDImagePool;
import org.gdstash.util.GDMsgFormatter;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class GDCollectionSetPane extends AdjustablePanel {
    private GDStashFrame frame;
    private List<GDItemSetInfo> data;
    private GDItemSetCollectionTableModel model;
    private JTable table;
    private JButton btnSearch;
    private JButton btnClear;
    private JButton btnHelp;
    private ItemSetSelectionPane pnlSelect;

    public GDCollectionSetPane(final GDStashFrame frame) {
        this.frame = frame;
        this.init();
    }

    @Override
    public void adjustUI() {
        Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntBorder = UIManager.getDefaults().getFont("TitledBorder.font");
        if (fntBorder == null) {
            fntBorder = fntLabel;
        }
        Font fntButton = UIManager.getDefaults().getFont("Button.font");
        if (fntButton == null) {
            fntButton = fntLabel;
        }
        Font fntTable = UIManager.getDefaults().getFont("TableHeader.font");
        if (fntTable == null) {
            fntTable = fntLabel;
        }
        fntLabel = fntLabel.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntBorder = fntBorder.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntButton = fntButton.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntTable = fntTable.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        if (this.btnSearch == null) {
            (this.btnSearch = new JButton()).addActionListener(new SearchItemsListener());
        }
        this.btnSearch.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_SEARCH"));
        this.btnSearch.setIcon(GDImagePool.iconBtnSearch24);
        this.btnSearch.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnSearch, "MNC_SEARCH");
        if (this.btnClear == null) {
            (this.btnClear = new JButton()).addActionListener(new ClearActionListener());
        }
        this.btnClear.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_CLEAR"));
        this.btnClear.setIcon(GDImagePool.iconItemDelete24);
        this.btnClear.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnClear, "MNC_CLEAR");
        if (this.btnHelp == null) {
            (this.btnHelp = new JButton()).addActionListener(new GDHelpActionListener("06_collection.html"));
        }
        this.btnHelp.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_HELP"));
        this.btnHelp.setIcon(GDImagePool.iconBtnQuestion24);
        this.btnHelp.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnHelp, "MNC_HELP");
        if (this.pnlSelect == null) {
            this.pnlSelect = new ItemSetSelectionPane();
        } else {
            this.pnlSelect.adjustUI();
        }
        if (this.table == null) {
            this.table = new JTable();
            final GDItemSetCollectionSorter sorter = new GDItemSetCollectionSorter();
            this.table.setRowSorter((RowSorter<? extends TableModel>) sorter);
            this.table.getTableHeader().addMouseListener(new SortListener());
            this.setItemSets(null);
        }
        this.table.getTableHeader().setFont(fntTable);
        this.table.setFont(fntLabel);
        int height = -1;
        if (this.data != null) {
            for (final GDItemSetInfo info : this.data) {
                final int h = info.getMaxImageHeight();
                if (h > height) {
                    height = h;
                }
            }
        }
        if (height == -1) {
            height = 12;
        }
        height = height * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
        this.table.setRowHeight(height);
        final GDItemSetCollectionTableModel model = (GDItemSetCollectionTableModel) this.table.getModel();
        model.adjustUI();
        this.updateTableColumns();
        final Border lowered = BorderFactory.createEtchedBorder(1);
        final Border raised = BorderFactory.createEtchedBorder(0);
        final Border compound = BorderFactory.createCompoundBorder(raised, lowered);
        final TitledBorder title = BorderFactory.createTitledBorder(compound, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_COLL_OVERVIEW"));
        title.setTitleFont(fntBorder);
    }

    private void init() {
        this.adjustUI();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel pnlMain = this.buildMainPanel();
        final JScrollPane scroll = new JScrollPane(pnlMain);
        scroll.getVerticalScrollBar().setUnitIncrement(100);
        scroll.getVerticalScrollBar().putClientProperty("JScrollBar.fastWheelScrolling", true);
        scroll.setWheelScrollingEnabled(true);
        layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(scroll));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(scroll));
        layout.setVerticalGroup(vGroup);
    }

    private JPanel buildMainPanel() {
        final BorderLayout layout = new BorderLayout();
        final JPanel panel = new JPanel();
        final JPanel pnlSearch = this.buildSearchPanel();
        final JPanel pnlTable = this.buildTablePanel();
        panel.setLayout(layout);
        panel.add(pnlSearch, "North");
        panel.add(pnlTable, "Center");
        this.setItemSets(this.data);
        return panel;
    }

    private JPanel buildSearchPanel() {
        final JPanel pnlButton = new JPanel();
        pnlButton.setLayout(new BorderLayout());
        pnlButton.add(this.btnSearch, "Center");
        pnlButton.add(this.btnClear, "West");
        pnlButton.add(this.btnHelp, "East");
        final JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(this.pnlSelect, "Center");
        panel.add(pnlButton, "North");
        return panel;
    }

    private JPanel buildTablePanel() {
        final JPanel panel = new JPanel();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JScrollPane scrTable = new JScrollPane(this.table);
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(scrTable));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(scrTable));
        layout.setVerticalGroup(vGroup);
        return panel;
    }

    private void updateTableColumns() {
        this.table.getColumnModel().getColumn(0).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(1).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(2).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(3).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(4).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(5).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(6).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(7).setCellRenderer(new GDItemSetTableCellRenderer());
        this.table.getColumnModel().getColumn(8).setCellRenderer(new GDItemSetTableCellRenderer());
        int scale = 100;
        int size = 12;
        if (GDStashFrame.iniConfig != null) {
            scale = GDStashFrame.iniConfig.sectUI.graphicScale;
            size = GDStashFrame.iniConfig.sectUI.fontSize;
        }
        this.table.getColumnModel().getColumn(0).setPreferredWidth(42 * size);
        this.table.getColumnModel().getColumn(1).setPreferredWidth(12 * size);
        this.table.getColumnModel().getColumn(2).setPreferredWidth(12 * size);
        this.table.getColumnModel().getColumn(3).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(4).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(5).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(6).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(7).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(8).setPreferredWidth(100 * scale / 100);
    }

    public void setItemSets(final List<GDItemSetInfo> list) {
        this.data = list;
        if (this.data != null) {
            Collections.<GDItemSetInfo>sort(this.data);
        }
        int height = -1;
        if (this.data != null) {
            for (final GDItemSetInfo info : this.data) {
                if (info == null) {
                    continue;
                }
                final int h = info.getMaxImageHeight();
                if (h <= height) {
                    continue;
                }
                height = h;
            }
        }
        if (height == -1) {
            height = 12;
        }
        this.model = new GDItemSetCollectionTableModel(this.data);
        this.table.setModel(this.model);
        this.table.setSelectionMode(0);
        this.table.getSelectionModel().addListSelectionListener(this.table);
        final GDItemSetCollectionSorter sorter = new GDItemSetCollectionSorter(this.model);
        this.table.setRowSorter((RowSorter<? extends TableModel>) sorter);
        this.updateTableColumns();
        final Rectangle rect = this.table.getVisibleRect();
        rect.setLocation(0, 0);
        this.table.scrollRectToVisible(rect);
        if (height != -1) {
            height = height * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            this.table.setRowHeight(height);
        }
    }

    private void search() {
        this.data = GDItemSetInfo.buildSetInfo();
        final int minLevel = this.pnlSelect.getMinLevel();
        final int maxLevel = this.pnlSelect.getMaxLevel();
        final List<String> rarities = this.pnlSelect.getRarityList();
        if (minLevel != -1 || maxLevel != -1 || !rarities.isEmpty()) {
            final List<GDItemSetInfo> filtered = new LinkedList<GDItemSetInfo>();
            for (final GDItemSetInfo set : this.data) {
                final int level = set.getItemSetLevel();
                final String rarity = set.getItemSetRarity();
                boolean keep = true;
                if (minLevel != -1 && minLevel > level) {
                    keep = false;
                }
                if (maxLevel != -1 && maxLevel < level) {
                    keep = false;
                }
                boolean found = false;
                for (final String selRarity : rarities) {
                    if (rarity.equals(selRarity)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    keep = false;
                }
                if (keep) {
                    filtered.add(set);
                }
            }
            this.data = filtered;
        }
        this.setItemSets(this.data);
    }

    private static class GDItemSetTableCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int col) {
            if (col <= 2) {
                final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
                final GDItemSetCollectionTableModel model = (GDItemSetCollectionTableModel) table.getModel();
                label.setForeground(model.getCellTextColor(row, col));
                label.setBackground(model.getCellBackgroundColor(row, col));
                return label;
            }
            if (col >= 3 && col <= 8) {
                final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
                final GDItemSetCollectionTableModel model = (GDItemSetCollectionTableModel) table.getModel();
                label.setIcon((Icon) value);
                label.setText(null);
                label.setHorizontalAlignment(0);
                label.setBackground(model.getCellBackgroundColor(row, col));
                return label;
            }
            return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        }
    }

    private class SearchItemsListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDCollectionSetPane.this.setCursor(Cursor.getPredefinedCursor(3));
            GDCollectionSetPane.this.search();
            GDCollectionSetPane.this.setCursor(Cursor.getDefaultCursor());
        }
    }

    private class ClearActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDCollectionSetPane.this.pnlSelect.clear();
        }
    }

    private class SortListener extends MouseAdapter {
        @Override
        public void mouseClicked(final MouseEvent ev) {
            final int idx = GDCollectionSetPane.this.table.getColumnModel().getColumnIndexAtX(ev.getX());
            final GDItemSetCollectionSorter sorter = (GDItemSetCollectionSorter) GDCollectionSetPane.this.table.getRowSorter();
            sorter.sort();
        }
    }
}
